﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Documents.Common.Interfaces;
using System.Xml;
using Documents.Common.Helpers;
using NWISDocuments.Repository.GetDocumentList;
using NWISDocuments.Repository.GetDocument;
using System.Text;

namespace NWISDocuments.Repository.Controllers
{
    public class DocumentController : Controller, IDocumentRepository
    {
        private static XmlDocument _documentTypes;

        /// <summary>
        /// Returns a set of categories, either from root or from a parent
        /// </summary>
        /// <param name="parentCategory"></param>
        /// <returns></returns>
        public ActionResult Categories(Guid? parentCategory)
        {
            return new ContentResult
            {
                Content = GetDocumentTypes(HttpContext.Server).OuterXml,
                ContentType = "application/xml"
            };
             
        }

        public ActionResult CareEvent(string careEventID)
        {
            return null;
        }

        public ActionResult CareEvents()
        {
            XmlDocument result = new XmlDocument();
            XmlNode container = result.CreateNode(XmlNodeType.Element, "", "CareEvents", "");
            result.AppendChild(container);
            return new ContentResult
            {
                Content = result.OuterXml,
                ContentType = "application/xml"
            };
        }
        
        
        private static XmlNode AddCategory(XmlNode parent, string categorytext, string categoryID)
        {
            XmlNode category = parent.OwnerDocument.CreateNode(XmlNodeType.Element, "", "Category", "");
            XmlNode categoryid = parent.OwnerDocument.CreateNode(XmlNodeType.Element, "", "CategoryID", "");
            categoryid.InnerText = categoryID;
            category.AppendChild(categoryid);

            XmlNode categoryname = parent.OwnerDocument.CreateNode(XmlNodeType.Element, "", "CategoryName", "");
            categoryname.InnerText = categorytext.ToString();
            category.AppendChild(categoryname);
            parent.AppendChild(category);
            return category;
        }
        /// <summary>
        /// Returns an individual category
        /// </summary>
        /// <param name="categoryID"></param>
        /// <returns></returns>
        public ActionResult Category(Guid categoryID)
        {
            return null;
        }

        public ActionResult Document(Guid documentID)
        {
            return GetDocument(documentID, null);
        }

        public ActionResult History(Guid DocumentSetID)
        {
            return GetDocument(null, DocumentSetID);
        }

        public ActionResult GetDocument(Guid? documentID, Guid? setID)
        { 
            GetDocumentRequest request = CreateDocumentRequest(documentID,setID);
            GetDocumentResponse response = GetDocument(request);
            XmlDocument result = XmlHelper.Serialize(response, null, null);
            XmlNode encodednode = result.DocumentElement["Document"]["DocumentVersion"]["Body"]["DocumentBase64"];
            byte[] DocumentBase64 = Convert.FromBase64String(encodednode.InnerXml);
            XmlDocument n = new XmlDocument();
            XmlNode documentXML = result.CreateNode(XmlNodeType.Element, "DocumentXML", "");
            n.LoadXml(System.Text.Encoding.UTF8.GetString(DocumentBase64));
            documentXML.InnerXml = n.OuterXml;
            result.DocumentElement["Document"]["DocumentVersion"]["Body"].AppendChild(documentXML);
            return new ContentResult
            {
                Content = result.OuterXml,
                ContentType = "application/xml"
            };
        
        }

        private XmlNode GetXml(byte[] p)
        {
            var d = new XmlDocument();
            d.LoadXml(Encoding.UTF8.GetString(p));
            return d;
        }
        


        private GetDocumentResponse GetDocument(GetDocumentRequest request)
        {
            NDRGetDocumentv01_CAService1 service = new NDRGetDocumentv01_CAService1();
            return service.GetDocument(request);
        }

        private NWISDocuments.Repository.GetDocument.IdentifierStructure CreateIdentifierStructureD(string domain, string value)
        {
            return new NWISDocuments.Repository.GetDocument.IdentifierStructure
            {
                Domain = domain,
                Value = value
            };
        }
        private GetDocumentRequest CreateDocumentRequest(Guid? documentId, Guid? setID)
        {
            GetDocumentRequest request = new GetDocumentRequest();

            request.Credentials = new NWISDocuments.Repository.GetDocument.CredentialsStructure()
            {
             ApplicationId = CreateIdentifierStructureD("CYMRU", "WCP"),
             UserId = CreateIdentifierStructureD("CYMRU", "pe027297")
            };
            if (documentId != null)
                request.DocumentId = documentId.ToString();
            if (setID != null)
                request.DocumentSupersessionSetId = setID.ToString();
            request.RetrievalMode = "TEST";

            return request;
        }

       

        private NWISDocuments.Repository.GetDocumentList.DocumentStructure[] DocumentList(GetDocumentListRequest request)
        {
            prjNDRGetDocumentListv05_OTDs_jcdGetDocumentListService o = new prjNDRGetDocumentListv05_OTDs_jcdGetDocumentListService();
            NWISDocuments.Repository.GetDocumentList.DocumentStructure[] result = o.GetDocumentList(request);
            return result;
        }

        GetDocumentListRequest CreateGetDocumentListRequest(string retrievalMode, Guid? categoryID, string DocumentTypeCode, string subjectIdentifiers)
        {
            string[] identifier = subjectIdentifiers.Split(new char[] { ',' },StringSplitOptions.RemoveEmptyEntries );
            NWISDocuments.Repository.GetDocumentList.IdentifierStructure[] SubjectIdentifierList = new NWISDocuments.Repository.GetDocumentList.IdentifierStructure[] { CreateIdentifierStructure(identifier[0], identifier[1])};
            NWISDocuments.Repository.GetDocumentList.DocumentAttributeStructure[] filters;
            if (DocumentTypeCode == null)
            {
                filters = GetFilters(categoryID);
            }
            else
            {
                NWISDocuments.Repository.GetDocumentList.DocumentAttributeStructure f = new NWISDocuments.Repository.GetDocumentList.DocumentAttributeStructure
                {
                    Attribute = "DocumentTypeCode",
                    Value = DocumentTypeCode,
                    Namespace = @"http://test"
                };
                filters = new NWISDocuments.Repository.GetDocumentList.DocumentAttributeStructure[] { f };
            }
            
            GetDocumentListRequest result = new GetDocumentListRequest
                       {
                           SubjectIdentifierList = SubjectIdentifierList
                           ,Credentials = new NWISDocuments.Repository.GetDocumentList.CredentialsStructure
                                        {   
                                            ApplicationId =  CreateIdentifierStructure("CYMRU", "WCP"),
                                            UserId = CreateIdentifierStructure("CYMRU", "pe027297")
                                        }
                           ,TaskCriteriaList = new NWISDocuments.Repository.GetDocumentList.TaskStructure[] { }
                           ,RetrievalMode = retrievalMode
                           ,AttributeCriteriaList = filters
                       };

            return result;
        }

        private NWISDocuments.Repository.GetDocumentList.IdentifierStructure CreateIdentifierStructure(string domain, string value)
        {
            return new NWISDocuments.Repository.GetDocumentList.IdentifierStructure
            {
                Domain = domain,
                Value = value
            };
        }

        private static XmlDocument GetDocumentTypes(HttpServerUtilityBase httpServerUtilityBase)
        {
            if (_documentTypes == null)
            {
                _documentTypes = new XmlDocument();
                _documentTypes.Load(httpServerUtilityBase.MapPath(@"\config")+"/DocumentTypes.config");
            }
            return _documentTypes;
        }

        private NWISDocuments.Repository.GetDocumentList.DocumentAttributeStructure[] GetFilters(Guid? categoryID)
        {
            if (categoryID==null)
                return new NWISDocuments.Repository.GetDocumentList.DocumentAttributeStructure[]{};

            // Now find out all document types within this category, since there is not NWIS link
            // we have to read these from an external file.
            XmlDocument docTypes = GetDocumentTypes(HttpContext.Server);
            // Now get the Node with name "Group" and categoryid of categoryID

            XmlNode categoryNode = docTypes.SelectSingleNode("DocumentTypes/Group[@categoryid='" + categoryID.ToString() + "']");
            if (categoryNode == null)
                // No category, WTF?
                return new NWISDocuments.Repository.GetDocumentList.DocumentAttributeStructure[] { };

            XmlNodeList doctypes = categoryNode.SelectNodes("DocumentType");
            List<NWISDocuments.Repository.GetDocumentList.DocumentAttributeStructure> result = new List<NWISDocuments.Repository.GetDocumentList.DocumentAttributeStructure>();
            foreach (XmlNode n in doctypes)
            { 
                NWISDocuments.Repository.GetDocumentList.DocumentAttributeStructure f = new NWISDocuments.Repository.GetDocumentList.DocumentAttributeStructure
                {
                   Attribute = "DocumentTypeCode", Value = n.Attributes["id"].Value, Namespace = @"http://test"   
                };
                result.Add(f);
            }
            return result.ToArray();
        }

       
        public ActionResult Documents(string documentType)
        {
            string subjectIdentifiers = Request["subjectIdentifiers"];
            GetDocumentListRequest request = CreateGetDocumentListRequest("TEST", null, documentType, subjectIdentifiers);
            XmlDocument result = XmlHelper.Serialize(DocumentList(request), null, "documents");
            return new ContentResult
            {
                Content = result.OuterXml,
                ContentType = "application/xml"
            };
        }

        

        private void AddVersion(XmlDocument result, XmlNode container, NWISDocuments.Repository.GetDocument.DocumentVersionHeaderStructure version)
        {
            XmlNode versionnode = result.CreateNode(XmlNodeType.Element, "", "version", "");

            XmlNode documenttitle = result.CreateNode(XmlNodeType.Element, "", "DocumentTitle", "");
            documenttitle.InnerText = version.VersionDescription;
            versionnode.AppendChild(documenttitle);

            XmlNode documentauthor = result.CreateNode(XmlNodeType.Element, "", "DocumentAuthor", "");
            NWISDocuments.Repository.GetDocument.DocumentAttributeStructure author = version.DocumentAttribute.Where(o => o.Attribute == "Author").FirstOrDefault();
            documentauthor.InnerText = author == null ? "Unknown" : author.Value;
            versionnode.AppendChild(documentauthor);

            XmlNode documentcreationdate = result.CreateNode(XmlNodeType.Element, "", "DocumentCreationDate", "");
            documentcreationdate.InnerText = version.DocumentDateTime.ToString("yyyy-MM-ddThh:mm:ssZ");
            versionnode.AppendChild(documentcreationdate);

            XmlNode revoked = result.CreateNode(XmlNodeType.Element, "", "Revoked", "");
            revoked.InnerText = version.Revoked.ToString();
            versionnode.AppendChild(revoked);

            XmlNode documentID = result.CreateNode(XmlNodeType.Element, "", "DocumentID", "");
            documentID.InnerText = version.DocumentId;
            versionnode.AppendChild(documentID);

            container.AppendChild(versionnode);
        }

      

        public ActionResult Search(object searchCriteria)
        {
            return null;
        }


        public ActionResult Revoke(Guid documentID)
        {
            return null;
        }

        public ActionResult Create(string DocumentType)
        {
            return null;
        }


        public ActionResult Countersign(Guid documentID)
        {
            return null;
        }

        public ActionResult Edit(Guid documentID)
        {
            return null;
        }

        public ActionResult Duplicate(Guid documentID)
        {
            return null;
        }

        [HttpPost]
        public ActionResult Store(XmlDocument document)
        {
            XmlDocument result = new XmlDocument();
            return new ContentResult
            {
                Content = result.OuterXml,
                ContentType = "application/xml"
            };
        }

        private void AddSimpleNode(string nodename, XmlNode storeresult, XmlDocument result, string value)
        {
            XmlNode documentsetid = result.CreateNode(XmlNodeType.Element, nodename, "");
            documentsetid.InnerText = value;
            storeresult.AppendChild(documentsetid);
        }

    }
}
